package maMetrics;

import java.util.Iterator;

import maConfigration.MetricSettings;
import maConfigration.ReadXMLConfig;
import maUtil.LogFile;
import maUtil.RecordUnit;
import maUtil.SortedRecords;

import com.telelogic.rhapsody.core.IRPAttribute;
import com.telelogic.rhapsody.core.IRPClass;
import com.telelogic.rhapsody.core.IRPGeneralization;
import com.telelogic.rhapsody.core.IRPInterfaceItem;
import com.telelogic.rhapsody.core.IRPOperation;
import com.telelogic.rhapsody.core.IRPPackage;
import com.telelogic.rhapsody.core.IRPProject;

public class MetricDIT extends MetricObject {
	
	
	SortedRecords _srProj = null;
	SortedRecords _srPkg = null;
	

	private static int[] _loopMaxNumber = new int[300];
	private static String[] _loopClsName = new String[300];
	private static int _loopCount = 0;	
	
	LogFile _logFile = null;
	LogFile _logFilePkg = null;
	protected LogFile _logRawData = null;
	
	int _nSum;
	
	public MetricDIT(MetricSettings ms)
	{
		super(ms);
		
		_sMetricName = "Metric: Depth of Inheritance Tree";
		if(_isApplyToPkg)
		{
			_srPkg = new SortedRecords(2000, _sMetricName + " Sorted By Packages");
		}
		if(_isApplyToProj)
		{
			_srProj = new SortedRecords(2000, _sMetricName + " Sorted By Project");
		}
		_logFile = new LogFile("MetricDIT.txt");
		_logFilePkg = new LogFile("MetricDITSortedByPkg.txt");
		
		if(_isLogRawData)
		{
			_logRawData = new LogFile("MetricDITRawData.csv");
			_logRawData.logLn("Value,Classname");
		}
		_nSum = 0;

	}

	/* Get the first ancestors and send them to a recursive method that will see which path
	 * that has most step. The function "getGeneralization" mess the method up a little because 
	 * it get all step directly but because the looping goes through all classes and their ancestors
	 * the result is correct*/
	public static int countDIT(IRPClass cls)
	{
		int highestDIT = 0;
		
		for(int i = 0; i < _loopMaxNumber.length; i++)
		{
			_loopMaxNumber[i] = 0;
		}
		
		Iterator generalizations = cls.getGeneralizations().toList().iterator();
		if(generalizations.hasNext())
		{
			_loopMaxNumber[0] = 1;
			recursiveGeneralizationLookup(generalizations);
		}
		
		for(int i = 0; i < _loopMaxNumber.length; i++)
		{
			if(_loopMaxNumber[i] > highestDIT)
				highestDIT = _loopMaxNumber[i];
		}
		return highestDIT;
	}
	
	/* Loops recursively through the inheritance tree upwards. The method is using a variant 
	 * of depth first search and store each path in a array as an integer*/
	private static void recursiveGeneralizationLookup(Iterator coll)
	{
		/*if(_firstRecursion)
		{
			_loopMaxNumber[_loopCount] = 1;
			_firstRecursion = false;
		}*/
		IRPGeneralization gen = null;
		Iterator nextLevel = null;
		
		while(coll.hasNext())
		{
			gen = (IRPGeneralization) coll.next();
			
			nextLevel = gen.getBaseClass().getGeneralizations().toList().iterator();
			if(nextLevel.hasNext())
			{
				_loopMaxNumber[_loopCount]++;
				recursiveGeneralizationLookup(nextLevel);
			}
			
			_loopCount++;
			if(coll.hasNext())
				_loopMaxNumber[_loopCount] = _loopMaxNumber[_loopCount-1];
			else
				_loopMaxNumber[_loopCount] = _loopMaxNumber[_loopCount-1] - 1;				
		}
	}

	@Override
	public int applyInProj(IRPProject proj) {
		// TODO Auto-generated method stub
		//if(_csvLogFileProj == null)
		/*_csvLogFileProj = new LogFile("MetricDIT"+ proj.getName() +".csv");
		if(!_isApplyToProj)
			return 0;
		if(_srProjCsv.getSize() > 0)
		{
			_csvLogFileProj.logLn("DIT,Class");
			_csvLogFileProj.logPln(_srProjCsv.getAllStringCSV());
		}
		//_csvLogFileProj = new LogFile("MetricDIT"+ proj.getName().toUpperCase() +".csv");
		_srProjCsv = new SortedRecords(10, "DIT,Class");*/
		
		int n = _nSum;
		_nSum = 0;
		return n;
	}

	private void log(String str) {
		// TODO Auto-generated method stub
		 _logFile.log(str);
	}

	@Override
	public int applyInPkg(IRPPackage pkg) {
		// TODO Auto-generated method stub
		if(!_isApplyToPkg)
			return 0;
		if(_srPkg.getSize() > 0)
		{
			_logFilePkg.log(_srPkg.getAllString());
		}
		_srPkg = new SortedRecords(2000, pkg.getName());
		return 0;
	}

	@Override
	public int applyInCls(IRPClass cls) {
		// TODO Auto-generated method stub
		_loopCount = 0;
		//_firstRecursion = true;
		/*if(_srProj == null)
		{
			_srProj = new SortedRecords(2000, _sMetricName + " " + cls.getProject().getName());
		}*/
		int n = countDIT(cls);
		RecordUnit ru = new RecordUnit(n, cls.getFullPathNameIn()+"in proj"+cls.getProject().getName().toUpperCase());
		if(_isApplyToPkg && n >= _srPkg.getMinValue() && !_srProj.contains(ru)) 
			_srPkg.add(ru);
		if(_isApplyToProj && n >= _srProj.getMinValue() && !_srProj.contains(ru))
			_srProj.add(ru);
		_nSum += n;
		
		if(_isLogRawData && n>0) 
			_logRawData.logLn(n + "," + cls.getFullPathNameIn());
		
		return n;
	}

	@Override
	public int applyInItf(IRPInterfaceItem itf) {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public int applyInOp(IRPOperation op) {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public int applyInAttr(IRPAttribute attrb) {
		// TODO Auto-generated method stub
		return 0;
	}


	@Override
	public void finish() {
		// TODO Auto-generated method stub
		if(_srProj != null) log(_srProj.getAllString());
		if(_srPkg != null) _logFilePkg.log(_srPkg.getAllString());

	}

}
